﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ITProject.Repository.Abstract;
using ITProject.Domain.Entities;
using ITProject.Domain;
using System.Xml;
using System.Data.Entity.Infrastructure;
using System.Data;
using System.Data.Objects;
using System.Data.Entity;

namespace ITProject.Repository.Concrete
{
    public class UserRepository : IUserRepository
    {
        private EFDataContext _dataContext = new EFDataContext();
        /// <summary>
        /// Dodawanie uzytkownika
        /// autor: Gajes
        /// </summary>
        /// <param name="user">encja uzytkownika do dodania</param>
        /// <returns>encja dodana</returns>
        public User Add(User user)
        {
            user = _dataContext.Users.Add(user);
            _dataContext.SaveChanges();
            return user;
        }

        public void SetUserLastVisitDate(User user)
        {
            if (user != null)
            {
                user.LastVisit = DateTime.Now;
                _dataContext.Entry(user).State = EntityState.Modified;
                _dataContext.SaveChanges();
            }
        }
        /// <summary>
        /// Dodawanie profilu uzytkownika do projektu
        /// Natalia Wyczislok
        /// </summary>
        /// <param name="profil"></param>
        /// <returns></returns>
        public Profil Add(Profil profil)
        {
            profil = _dataContext.Profil.Add(profil);
            _dataContext.SaveChanges();
            return profil;
        }
        /// <summary>
        /// pobiera uzytkownikow o pdoanym loginie
        /// autor: Gajes
        /// </summary>
        /// <param name="login"></param>
        /// <returns></returns>
        public User GetUserByLogin(string login)
        {
            return _dataContext.Users.Where(x => x.Login == login).FirstOrDefault();
        }
       /// <summary>
       /// Zwraca profil danego uzytkownika
       /// Natalia Wyczislok
       /// </summary>
       /// <param name="id"></param>
       /// <returns></returns>
        public Profil GetProfilById(int id)
        {
            return  _dataContext.Profil.Where(x => (x.Id == id)).FirstOrDefault();
        }
        /// <summary>
        /// Sprawdzanie, czy istnieje konto o takim mailu lub loginie-uzywane przy rejestracji
        /// autor: Gajes
        /// </summary>
        /// <param name="login"></param>
        /// <param name="email"></param>
        /// <returns></returns>
        public bool IsAccountExist(string login, string email)
        {
            int count = _dataContext.Users.Where(x => x.Login == login || x.Email == email).Count();
            if (count == 0)
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        /// <summary>
        /// Dodawanie hashu do tabeli
        /// autor: Gajes
        /// </summary>
        /// <param name="id">id uzytkownika</param>
        /// <param name="hash">hash aktywacyjny</param>
        public void AddHash(int id, string hash)
        {
            var activationHash = new ActivationHash { Id = id, Hash = hash };
            _dataContext.ActivationHash.Add(activationHash);
            _dataContext.SaveChanges();
        }
        /// <summary>
        /// Metoda aktywujaca konto po wejsciu z linku
        /// autor: Gajes
        /// </summary>
        /// <param name="hash"></param>
        /// <returns></returns>
        public bool ActivateAccount(string hash)
        {
            var hashes = _dataContext.ActivationHash.Where(x => x.Hash == hash);
            if (hashes.Count() != 0)
            {
                var account = _dataContext.Users.Where(x => x.Id == hashes.FirstOrDefault().Id).FirstOrDefault();
                account.State = (byte)UserState.Active;
                _dataContext.Entry(account).State = EntityState.Modified;
                _dataContext.SaveChanges();
                return true;
            }
            return false;
        }
        /// <summary>
        /// Metoda do pobierania liczby nieprzeczytanych wiadomości użytkownika.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="user">Użytkownik dla którego sprawdzamy liczbę nieprzeczytanych wiadmości.</param>
        /// <returns>Liczba nie przeczytanych wiadomości.</returns>
        public int GetUnreadMessages(User user)
        {
            if (user == null)
                return 0; 
            return _dataContext.Message.Where(x => (x.Receiver == user.Id && x.Readed==false)).Count();
        }

        /// <summary>
        /// Edytuje dane uzytkownika
        /// Natalia Wyczislok
        /// </summary>
        /// <param name="user">dane z tabeli users</param>
        /// <param name="profil">dane z tabeli profil</param>
        public void EditUserData(User user, Profil profil,string login)
        {
            User u = this.GetUserByLogin(login);
            u.LastName = user.LastName;
            if(user.Password!=null && user.Password!="")
                u.Password = user.Password;
            u.FirstName = user.FirstName;
            u.Email = user.Email;
            u.BirthDate = user.BirthDate;
            DbEntityEntry entry = _dataContext.Entry(u);
            entry.State = EntityState.Modified;
            _dataContext.SaveChanges();
            Profil p = this.GetProfilById(u.Id);
            if (p == null)
            { 
                profil.Id = u.Id;
                this.Add(profil);
            }
            else
            {
                p.About = profil.About;
                p.AvatarPath = profil.AvatarPath;
                p.City = profil.City;
                p.Country = profil.Country;
                p.Experience = profil.Experience;
                p.Interest = profil.Interest;
                p.Skills = profil.Skills;
                entry = _dataContext.Entry(p);
                entry.State = EntityState.Modified;
            }
            _dataContext.SaveChanges();

        }

        /// <summary>
        /// Metod do pobierania loginu mając tylko identyfikator użytkownika (np. klucz obcy innej tabeli).
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="id">Identyfikator użytkownika.</param>
        /// <returns>Encja użytkownika.</returns>
        public User GetUserById(int id)
        {
            return _dataContext.Users.Where(x => (x.Id == id)).FirstOrDefault();
        }
        /// <summary>
        /// Metoda do pobrania nazwy avatara użytkownika o danym loginie
        /// Natalia Wyczislok
        /// </summary>
        /// <param name="Login"> Login uzytkownika</param>
        /// <returns>nazwa pliku avatara</returns>
        public string GetAvatarByLogin(string Login)
        {
            User u = this.GetUserByLogin(Login);
            if (u == null)
                return "";
            Profil p = this.GetProfilById(u.Id);
            
            string avatar = null;
            if (p != null)
                avatar = p.AvatarPath;
            if (avatar == null)
                if (u.Sex == 'K'.ToString())
                    avatar = "AvatarW.png";
                else
                    avatar = "AvatarM.png";
            return avatar;

        }
        
        int usersinSite = 10;
        /// <summary>
        /// Metoda do pobierania listy danych podstawowych o uzytkownikach w zaleznosci od strony
        /// Natalia Wyczislok
        /// </summary>
        /// <param name="str">strona</param>
        /// <returns>Lista encji User</returns>
        public IEnumerable<User> GetAllUsers(int str)
        {
            int od=str==0?0:usersinSite*str;
            int doo=usersinSite+str*usersinSite;
            IEnumerable<User> odd=_dataContext.Users.Where(x=>(x.State!=(byte)UserState.Inactive)).OrderBy(x => x.Login).Take(doo);
            int il = odd.Count();
            IEnumerable<User> dooo = _dataContext.Users.Where(x=>(x.State!=(byte)UserState.Inactive)).OrderBy(x => x.Login).Take(od);
            return odd.Except(dooo).AsEnumerable();
        }
        /// <summary>
        /// Metoda do pobierania listy danych ponadpodstawowych o uzytkownikach 
        /// Natalia Wyczislok
        /// </summary>
        /// <returns>Lista encji profil</returns>
        public IEnumerable<Profil> GetAllProfil()
        {
            return _dataContext.Profil.AsEnumerable();
        }

        /// <summary>
        /// Metoda pozwalająca pobrać wszystkich użytkowników serwisu ITProject.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <returns>Tablica wszystkich aktywnych użytkowników serwisu ITProject</returns>
        public User[] GetAllUsers()
        {
            return _dataContext.Users.Where(x=>(x.State!=(byte)UserState.Inactive)).ToArray();
        }

        /// <summary>
        /// Metoda pobiera ilosc stron z informacjami o uzytkowniku, bierze pod uwage ilosc uzytkownikow oraz ilosc mozliwych na stronie
        /// Natalia Wyczislok
        /// </summary>
        /// <returns>ilość stron</returns>
        public int getCountSite()
        {
            int il=_dataContext.Users.Where(x=>(x.State!=(byte)UserState.Inactive)).Count();
            return il / usersinSite + 1;
        }
        /// <summary>
        /// Metoda do pobrania statusu o danym id
        /// Natalia Wyczislok
        /// </summary>
        /// <param name="id">id statusu</param>
        /// <returns>status uzytkownika</returns>
        public UserState GetUserState(int id)
        {
            switch (id)
            {
                case 1: return UserState.Active;
                case 2: return UserState.Inactive;
                case 3: return UserState.Baned;
                default: return 0;
            }
        }
        /// <summary>
        /// Metoda do pobrania roli  o danym id
        /// Natalia Wyczislok
        /// </summary>
        /// <param name="id">id roli</param>
        /// <returns>rola uzytkownika</returns>
        public UserRole GetUserRole(int id)
        {
            switch (id)
            {
                case 1: return UserRole.User;
                case 2: return UserRole.Supervisor;
                case 3: return UserRole.Manager;
                default: return 0;
            }
        }

        public List<SVNHistory> GetRepositoryEntry(int projectID, string userName)
        {
            int userId = _dataContext.Users.Where(x => x.Login == userName).Select(x => x.Id).FirstOrDefault();
            return _dataContext.SVNHistory.Where(x => x.ProjectId == projectID && x.UserId == userId).ToList();
        }
    }
 
}
